package com.av.db.layer.impl;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.av.db.dataobjects.Usuario;
import com.av.db.layer.interfaces.UsuarioLayer;
import com.av.exceptions.AvException;

/**
 * Clase que contiene la implementacion de funciones para la tabla de usuarios
 * utilizando la tecnologia de Hibernate
 * 
 * @author Victor J Morales R
 * 
 */
public class UsuarioLayerImpl extends HibernateDaoSupport implements
		UsuarioLayer {

	private static Logger log = Logger.getLogger(UsuarioLayerImpl.class);

	/**
	 * Funcion que actualiza un usuario existente en la base de datos
	 * configurada
	 */
	@Override
	public void actualizar(Usuario usuario) throws AvException {
		log.info("Inicio - actualizar(Usuario usuario)");
		log.debug("Id : " + usuario.getId());
		log.debug("Usuario : " + usuario.toString());

		if (usuario == null) {
			log.error("No se puede actualizar un usuario nulo");
			throw new AvException("Usuario nulo a ser actualizado");
		}

		if (usuario.getId() < 0) {
			log.error("No se puede actualizar un usuario con identificador "
					+ "invalido");
			throw new AvException("Usuario con identificador invalido a ser "
					+ "actualizado");
		}

		getHibernateTemplate().update(usuario);

		log.info("Fin - actualizar(Usuario usuario)");
	}// actualizar

	/**
	 * Funcion que agrega un usuario en la base de datos configurada
	 */
	@Override
	public void agregar(Usuario usuario) throws AvException {
		log.info("Inicio - agregar(Usuario usuario)");
		log.debug("Usuario : " + usuario.toString());

		if (usuario == null) {
			log.error("No se puede agregar un usuario nulo");
			throw new AvException("Usuario nulo a ser agregado");
		}

		getHibernateTemplate().save(usuario);

		log.info("Fin - agregar(Usuario usuario)");
	}// agregar

	/**
	 * Funcion que elimina un usuario especifico de la base de datos configurada
	 */
	@Override
	public void eliminar(Usuario usuario) throws AvException {
		log.info("Inicio - eliminar(Usuario usuario)");
		log.debug("Usuario : " + usuario.toString());

		if (usuario == null) {
			log.error("No se puede eliminar un usuario nulo");
			throw new AvException("Usuario nulo a ser eliminado");
		}

		if (usuario.getId() < 0) {
			log
					.error("No se puede eliminar un usuario con identificador negativo");
			throw new AvException("Identificador negativo");
		}

		getHibernateTemplate().delete(usuario);

		log.info("Fin - eliminar(Usuario usuario)");
	}// eliminar

	/**
	 * Funcion que obtiene un usuario activo a partir de su username
	 */
	@Override
	public Usuario obtenerUsuarioPorUsername(String username)
			throws AvException {
		log.info("Inicio - obtenerUsuarioPorUsername(String username)");
		log.debug("Username : " + username);

		if (username == null) {
			log
					.error("No se puede obtener un usuario a partir de un valor nulo");
			throw new AvException(
					"No se puede obtener un usuario a partir de un valor nulo");
		}

		List<?> l = getSession().createCriteria(Usuario.class).add(
				Restrictions.eq(Usuario.USER, username)).add(
				Restrictions.eq(Usuario.ACTIVO, true)).setResultTransformer(
				Criteria.DISTINCT_ROOT_ENTITY).addOrder(Order.asc(Usuario.ID))
				.setMaxResults(1).list();

		if (l != null && l.size() > 0) {
			return (Usuario) l.get(0);
		}

		return null;
	}// obtenerUsuarioPorUsername

	/**
	 * Funcion que obtiene un usuario mediante identificador, de la base de
	 * datos configurada
	 */
	@Override
	public Usuario obtener(int id) {
		log.info("Inicio - obtener(int id)");
		log.debug("Id : " + id);

		if (id < 0) {
			log
					.warn("No se puede obtener un usuario con identificador negativo");
			return null;
		}

		Usuario tmp = getHibernateTemplate().get(Usuario.class, id);

		if (tmp != null) {
			log.debug("Usuario : " + tmp.toString());
		} else {
			log.debug("Usuario no encontrado");
		}

		log.info("Fin - obtener(int id)");

		return tmp;
	}// obtener

	/**
	 * Funcion que obtiene un conjunto de todos los usuarios registrados en la
	 * base de datos configurada
	 */
	@Override
	public Usuario[] obtener() {
		log.info("Inicio - obtener()");

		List<?> l = getSession().createCriteria(Usuario.class)
				.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).addOrder(
						Order.asc(Usuario.ID)).list();

		Usuario[] tmp = null;
		if (l != null && l.size() > 0) {
			log.debug("Cantidad obtenida : " + l.size());
			tmp = new Usuario[l.size()];
			l.toArray(tmp);
		}

		log.info("Fin - obtener()");

		return tmp;
	}// obtener

	/**
	 * Funcion que obtiene todos los registros activos del sistema
	 */
	@Override
	public Usuario[] obtenerActivos() {
		log.info("Inicio - obtenerActivos()");

		List<?> l = getSession().createCriteria(Usuario.class).add(
				Restrictions.eq(Usuario.ACTIVO, true)).setResultTransformer(
				Criteria.DISTINCT_ROOT_ENTITY).addOrder(Order.asc(Usuario.ID))
				.list();

		Usuario[] tmp = null;
		if (l != null && l.size() > 0) {
			log.debug("Cantidad obtenida : " + l.size());
			tmp = new Usuario[l.size()];
			l.toArray(tmp);
		}

		log.info("Fin - obtenerActivos()");

		return tmp;
	}// obtenerActivos

	@Override
	public Usuario[] obtenerInactivos() {
		log.info("Inicio - obtenerInactivos()");

		List<?> l = getSession().createCriteria(Usuario.class).add(
				Restrictions.eq(Usuario.ACTIVO, false)).setResultTransformer(
				Criteria.DISTINCT_ROOT_ENTITY).addOrder(Order.asc(Usuario.ID))
				.list();

		Usuario[] tmp = null;
		if (l != null && l.size() > 0) {
			log.debug("Cantidad obtenida : " + l.size());
			tmp = new Usuario[l.size()];
			l.toArray(tmp);
		}

		log.info("Fin - obtenerInactivos()");

		return tmp;
	}
}// UsuarioLayerImpl